﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using BZ.Logger;
using HalconDotNet;
using HZH_Controls;
using NDK.Module.BLL;
using NDK.Module.Model;
using NDK.Motion.BLL;
using NDK.Motion.Monitor;
using Newtonsoft.Json;
using VisionPlatform;

namespace NDK.Module.StationLogic
{
    public class Station_上料定位 : StationLogic
    {
        #region 通用
        public override event PropertyChangedEventHandler PropertyChanged;

        public static Station_上料定位 Instance = new Station_上料定位();

        private bool IsOK;
        private Dictionary<string, double> DicFixValue;
        public Stopwatch SunWayUp = new Stopwatch();
        public string StationName = "Station00上料定位";
        //步骤字段、属性
        private StationStep _Step = StationStep.等待相机定位信号;
        [Monitor(Description = "当前步骤")]
        public StationStep Step
        {
            get
            {
                return _Step;
            }
            set
            {
                if (_Step != value)
                {
                    if (!Common.BP_是否屏蔽计时)
                    {
                        WriteStationCTLog("StationCTLog", $"{_Step}用时为：{swStepTime.ElapsedMilliseconds} ms");
                        swStepTime.Restart();
                    }
                    _Step = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(value.ToString()));
                }
            }
        }
        public double waitct;
        #endregion

        /// <summary>
        /// 工站初始化
        /// </summary>
        public override void Init()
        {
            base.Init();
            logBaseInfo = "上料定位流程";
            Step = StationStep.等待相机定位信号;
            FlowCT = new Stopwatch();
            WaitCT = new Stopwatch();
            MVCCD = Common.HikVisionList[3];
            QueueImage1 = new ConcurrentQueue<MeasureImage>();
            WaitCT.Start();
        }


        public override void ActionProcess()
        {
            try
            {
                switch (Step)
                {
                    case StationStep.等待相机定位信号:
                        if (!Common.BP_屏蔽PLC)
                        {
                            if (Common.PLCAdr.DicInPutValue[PLCInPut.上料拍照])
                            {
                                Step = StationStep.触发相机拍照取图;
                                SunWayUp.Restart();
                            }
                            waitct = WaitCT.Elapsed.TotalSeconds;
                        }
                        break;

                    case StationStep.触发相机拍照取图:
                        WaitCT.Restart();
                        Machine.imageLights_上料定位光源.Open();
                        Thread.Sleep(Common.IP_光源延时);
                        if (CCDImage(ref HImageCCD))
                        {
                            DicFixValue = new Dictionary<string, double>();
                            Step = Common.IsEmptyModel ? StationStep.等待定位信号关闭 : StationStep.调用算法定位处理;
                        }
                        //HImage hImage = HImageCCD.Clone();
                        //var DT = DateTime.Now.ToString("HH:mm:ss") + ".bmp";
                        //HalconDotNet.HOperatorSet.WriteImage(hImage, "bmp", 0, $"F:\\Data\\output\\UPCCD\\{DT}");
                        //PublicMethod.SaveImageWithBarCode(hImage, $"F:\\Data\\output\\UPCCD", "上料定位");
                        Machine.imageLights_上料定位光源.Close();
                        SunWayUp.Restart();
                        break;

                    case StationStep.调用算法定位处理:
                        if (VisionProcess(HImageCCD, ref DicFixValue))
                        {
                            var X = Math.Round(DicFixValue["RX1"] + Common.DP_定位偏移X, 2);
                            var Y = Math.Round(DicFixValue["RY1"] + Common.DP_定位偏移Y, 2);
                            var R = Math.Round(DicFixValue["RU1"] + Common.DP_定位偏移R, 2);

                            DicFixValue["RX1"] = X == 0 ? 0.001 : X;
                            DicFixValue["RY1"] = Y == 0 ? 0.001 : Y;
                            DicFixValue["RU1"] = R == 0 ? 0.001 : R;
                            IsOK = DicFixValue.Values.All(x => x != 9999);
                            if (!IsOK)
                            {
                                if (AlarmPause("定位拍照NG", $"定位拍照NG，请检查", "调整物料位置", "重新检测", "忽略报警，继续运行") == DialogResult.OK)
                                {
                                    break;
                                }
                            }
                            Step = StationStep.发送算法定位补偿;
                        }
                        break;

                    case StationStep.发送算法定位补偿:
                        if (PLCWriteMethod(logBaseInfo, (Common.PLCAdr.DicOutPutReal[PLCOutPutReal.补偿X], null, (float)DicFixValue["RX1"]),
                                                       (Common.PLCAdr.DicOutPutReal[PLCOutPutReal.补偿Y], null, (float)DicFixValue["RY1"]),
                                                       (Common.PLCAdr.DicOutPutReal[PLCOutPutReal.补偿R], null, (float)DicFixValue["RU1"]),
                                                       (Common.PLCAdr.DicOutPutBool[IsOK ? PLCOutPutBool.定位OK : PLCOutPutBool.定位NG], true, null)))
                        {
                            UILog_Info($"[{logBaseInfo}] 发送定位结果:{(IsOK ? "OK" : "NG")}, X:{DicFixValue["RX1"]},Y:{DicFixValue["RY1"]},R:{DicFixValue["RU1"]}");
                            Step = StationStep.等待定位信号关闭;
                        }
                        break;

                    case StationStep.等待定位信号关闭:
                        if (!Common.PLCAdr.DicInPutValue[PLCInPut.上料拍照])
                        {
                            PLCWriteMethod(logBaseInfo, (Common.PLCAdr.DicOutPutBool[IsOK ? PLCOutPutBool.定位OK : PLCOutPutBool.定位NG], false, null));
                            Step = StationStep.等待相机定位信号;
                        }
                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                UILog_Error($"[{logBaseInfo}] {ex.Message}");
            }
        }

        public override void EmptyActionProcess()
        {
            ActionProcess();
        }

        public override void GRRActionProcess()
        {
            ActionProcess();
        }

        public enum StationStep
        {
            等待相机定位信号,
            触发相机拍照取图,
            调用算法定位处理,
            发送算法定位补偿,
            等待定位信号关闭,
        }

        private bool VisionProcess(HImage image, ref Dictionary<string, double> dic)
        {
            try
            {
                if (Common.CurProType != "Product" && Common.CurProType != "Product1")
                {
                    VisionEngine = new VisionManager.Engine("Block定位");
                    VisionEngine.SetInputImage("Image", image);
                    VisionEngine.ActionFun();
                    var re1 = VisionEngine.GetOutputString("PositionData1");
                    if (!string.IsNullOrEmpty(re1))
                    {
                        dic = JsonConvert.DeserializeObject<Dictionary<string, double>>(re1);
                    }
                }
                else
                {
                    VisionEngine = new VisionManager.Engine("Position");
                    VisionEngine.SetInputImage("Image", image);
                    VisionEngine.ActionFun();
                    var re = VisionEngine.GetOutputString("PositionData");
                    if (!string.IsNullOrEmpty(re))
                    {
                        dic = JsonConvert.DeserializeObject<Dictionary<string, double>>(re);
                    }
                }

            }
            catch (Exception ex)
            {
                AlarmPause("算法异常", $"{logBaseInfo}算法异常,{ex}", "检查算法", "重新定位");
                return false;
            }
            return true;
        }
    }

}
